home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Adobe Graphics & Publishing SDK 1996 December
/
Adobe Graphics & Publishing SDK 1996 December.iso
/
mac
/
Premiere 4.2 SDK r3 Mac
/
Examples
/
Projects
/
Generic EDL
/
Generic EDL.c
< prev
next >
Wrap
Text File
|
1996-01-25
|
21KB
|
637 lines
//========================================================================================
//
// Generic EDL.c - A generic edit decision list export module.
//
// Written by Randy Ubillos and Bryan K. "Beaker" Ressler.
//
// Copyright ⌐ 1993-96, Adobe Systems Incorporated, all rights reserved worldwide.
//
// Version 1.00 10/20/93 Original version.
// Version 1.01 9/12/95 Updated for 4.0.
// Version 1.02 10/8/95 Updated for 4.2 and CW7.
//
// NOTE TO DEVELOPERS: This file contains a number of routines that are useful in the
// parsing of Premiere's nested block EDL data structure. Not all the routines are
// actually used by the Generic EDL -- they are provided in case you need them.
//
//========================================================================================
//========================================================================================
// Includes - use precompiled headers if compiling with CodeWarrior.
//========================================================================================
#ifdef __MWERKS__
#ifdef powerc
#include "PremierePPC"
#else
#include "Premiere68k"
#endif
#else
#include "Premiere.h"
#endif
#include <stdarg.h>
//========================================================================================
// Constants
//========================================================================================
enum { // Resource IDs
grStrings = 128, // STR# - standard file strings
grKeyTypes = 129 // STR# - names of the key types
};
enum { // Strings in our STR# grStrings
gsPrompt = 1,
gsSuffix = 2
};
//========================================================================================
// Static prototypes
//========================================================================================
static short WriteFile(short ref, Ptr data, long length);
static short SendChar(short ref, char ch);
static short WriteString(short ref, char *str);
static short SendNum(short ref, long num);
static short SendStr(short ref, char *fmt, ...);
static short SendIndent(short ref, short amount);
static short ParseBlock(BlockRec *theblock, short ref, short indent);
//========================================================================================
// Export module entry point
//========================================================================================
pascal short main (short selector, ExportHandle theData)
{
Str63 prompt, defaultName, suffix;
StandardFileReply reply;
short result = 0, err, ref;
// Act according to the selector
switch (selector) {
case exExecute:
// Get the standard put file prompt and the EDL filename suffix from our
// string list. Append the suffix to the current project name.
GetIndString(prompt, grStrings, gsPrompt);
GetIndString(suffix, grStrings, gsSuffix);
BlockMove((*theData)->projectName, defaultName,
(*theData)->projectName[0] + 1);
Append(defaultName, suffix);
// Ask the user for an output filespec.
StandardPutFile(prompt, defaultName, &reply);
if (reply.sfGood) {
// Delete any existing file with that name, then create and open a new
// text file as specified by the user.
FSpDelete(&reply.sfFile);
// The following is ???? followed by TEXT
err = FSpCreate(&reply.sfFile, 0x3f3f3f3f, 0x54455854, reply.sfScript);
if (err == noErr)
err = FSpOpenDF(&reply.sfFile, fsRdWrPerm, &ref);
// Now call ParseBlock to parse the project and output an EDL to the
// text file.
if (err == noErr) {
HLock((*theData)->dataHandle);
ParseBlock((BlockRec *)*(*theData)->dataHandle, ref, 0);
HUnlock((*theData)->dataHandle);
FSClose(ref);
MakeWindowForTextFile(&reply.sfFile);
}
}
break;
case exTrue30fps:
// Return true here to get time values in 1/30 instead of 1/29.97.
result = true;
break;
}
return(result);
}
//========================================================================================
// Write data to a file
//========================================================================================
static short WriteFile(short ref, Ptr data, long length)
{
long count;
count = length;
return(FSWrite(ref, &count, data));
}
//========================================================================================
// Send a character to a file
//========================================================================================
static short SendChar(short ref, char ch)
{
return(WriteFile(ref, &ch, 1));
}
//========================================================================================
// Send a string to a file
//========================================================================================
static short WriteString(short ref, char *str)
{
return(WriteFile(ref, str + 1, str[0]));
}
//========================================================================================
// Send a number to a file
//========================================================================================
static short SendNum(short ref, long num)
{
Str127 str;
NumToString(num, str);
return(WriteString(ref, (char *)str));
}
//========================================================================================
// Send a formatted string to a file. The parameter fmt is a format string akin to that
// of printf (see table below)
//
// Specifier Parameter Description
// ------------ ----------- ------------------------------------------------------------
// %d long Substitute a long integer value output in decimal
// %s char * Substitute a string
// %t OSType Substitute an OSType value (output as a 4-character string)
// %b char Substitute a byte value output in binary
//========================================================================================
static short SendStr(short ref, char *fmt, ...)
{
Str31 temp;
va_list parm;
long parms[kMaxExpandParms];
char *where, *last, *start, oldChar;
short param = 0, err = 0, i, num;
// Unroll the parameters in advance (required for PowerPC)
va_start(parm, fmt);
for (i = 0; i < kMaxExpandParms; i++)
parms[i] = va_arg(parm, long);
va_end(parm);
where = fmt + 1;
last = fmt + fmt[0];
while (err == noErr && (where <= last)) {
start = where;
if (where[0] == '%') {
switch (where[1]) {
case 'd': // %d means decimal
err = SendNum(ref, parms[param++]);
break;
case 's': // %s means string
err = WriteString(ref, (char *)parms[param++]);
break;
case 't': // %t means OSType
temp[0] = 4;
*((long*)(temp + 1)) = parms[param++];
err = WriteString(ref, (char *)temp);
break;
case 'b': // %b means binary
temp[0] = 8;
num = parms[param++];
for (i = 0; i <= 7; i++)
temp[1 + i] = num & (0x0080 >> i) ? '1' : '0';
err = WriteString(ref, (char *)temp);
break;
}
where += 2;
} else { // no substitution
while ((where <= last) && (where[0] != '%'))
where++;
oldChar = start[-1];
start[-1] = where - start;
err = WriteString(ref, (char *)(start - 1));
start[-1] = oldChar;
}
}
return(err);
}
//========================================================================================
// Send out spaces to do an indent
//========================================================================================
static short SendIndent(short ref, short amount)
{
short i, err = 0;
for (i = 0; i < amount && err == noErr; i++)
err = SendChar(ref, 9);
return(err);
}
//========================================================================================
// Take apart a block -- this routine is called recursively.
//========================================================================================
static short ParseBlock(BlockRec *theBlock, short ref, short indent)
{
short i, count, sValue, err = 0, mapping;
long len, lValue;
Rec_BLOK rBLOK;
Rec_TREC rTREC;
Rec_CLIP rCLIP;
Rec_RPNT rRPNT;
Rec_MREC rMREC;
Rec_VIDI rVIDI;
Rec_FXOP rFXOP;
Rec_TIMB rTIMB;
FSSpec rFILE;
RGBColor theColor;
Rect box;
Point pt;
Str31 str;
Ptr pblock, p;
// Indent and open this block
err = SendIndent(ref, indent);
if (err == noErr) err = SendChar(ref, '[');
// Switch on all known types of block
if (err == noErr) switch (theBlock->type) {
case bBLOK:
len = sizeof(Rec_BLOK);
ExtractBlockData(theBlock, &rBLOK, &len);
err = SendStr(ref, (char*)"\p'Adobe Premiere¬ 4.2 Generic Edit Decision List', Work_Start=%d, Work_End=%d",
rBLOK.start, rBLOK.end);
break;
case bTRKB:
err = SendStr(ref, (char*)"\pTracks", nil);
break;
case bTRAK:
err = SendStr(ref, (char*)"\pTrack #%d", theBlock->theID);
break;
case bFVID:
err = SendStr(ref, (char*)"\pVideo", nil);
break;
case bFSUP:
err = SendStr(ref,(char*)"\pSuperImpose",nil);
break;
case bFAUD:
err = SendStr(ref, (char*)"\pAudio", nil);
break;
case bAMAP:
len = sizeof(mapping);
ExtractBlockData(theBlock, &mapping, &len);
err = SendStr(ref, (char*)"\pMapping=%b", mapping);
break;
case bFF_X:
err = SendStr(ref, (char*)"\pFX", nil);
break;
case bTREC:
len = sizeof(Rec_TREC);
ExtractBlockData(theBlock, &rTREC, &len);
err = SendStr(ref, (char*)"\pTrack_Record #%d, ClipID=%d, Start=%d, End=%d",
theBlock->theID, rTREC.clipID, rTREC.start, rTREC.end);
break;
case bRBND:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pRubberBand, Max=%d", sValue);
break;
case bRPNT:
len = sizeof(Rec_RPNT);
ExtractBlockData(theBlock, &rRPNT, &len);
err = SendStr(ref, (char*)"\pBand_Point #%d,h=%d,v=%d",
theBlock->theID, rRPNT.h, rRPNT.v);
break;
case bFXOP:
len = sizeof(Rec_FXOP);
ExtractBlockData(theBlock, &rFXOP, &len);
err = SendStr(ref, (char*)"\pFX_Options,Corners=%b,Direction=%d,Start=%d,End=%d",
rFXOP.corners, rFXOP.direction, rFXOP.startPercent, rFXOP.endPercent);
break;
case bFXDF:
len = sizeof(long);
ExtractBlockData(theBlock, &lValue, &len);
err = SendStr(ref, (char*)"\pFX_Type=%t", lValue);
break;
case bEDGE:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pEdge,Thickness=%d", sValue);
break;
case bMPNT:
len = sizeof(Point);
ExtractBlockData(theBlock, &pt, &len);
err = SendStr(ref, (char*)"\pRef_Point,h=%d,v=%d",
theBlock->theID, pt.h, pt.v);
break;
case bSPNT:
len = sizeof(Point);
ExtractBlockData(theBlock, &pt, &len);
err = SendStr(ref, (char*)"\pStart_Point,h=%d,v=%d",
theBlock->theID, pt.h, pt.v);
break;
case bEPNT:
len = sizeof(Point);
ExtractBlockData(theBlock, &pt, &len);
err = SendStr(ref, (char*)"\pEnd_Point,h=%d,v=%d",
theBlock->theID, pt.h, pt.v);
break;
case bOVER:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
GetIndString(str, 129, sValue+1);
err = SendStr(ref, (char*)"\pOverlay, Type='%s'", (long)str);
break;
case bCOLR:
len = sizeof(RGBColor);
ExtractBlockData(theBlock, &theColor, &len);
err = SendStr(ref, (char*)"\pColor,Red=%d,Green=%d,Blue=%d",
theColor.red, theColor.green, theColor.blue);
break;
case bSIMI:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pSimilarity=%d", sValue);
break;
case bBLND:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pBlend=%d", sValue);
break;
case bTHRS:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pThreshold=%d", sValue);
break;
case bCUTO:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pCutoff=%d", sValue);
break;
case bALIA:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pAnti-Aliasing=%d", sValue);
break;
case bSHAD:
err = SendStr(ref, (char*)"\pShadow", nil);
break;
case bRVRS:
err = SendStr(ref, (char*)"\pKey_Reversed", nil);
break;
case bGARB:
len = sizeof(Rect);
ExtractBlockData(theBlock, &box, &len);
err = SendStr(ref, (char*)"\pGarbage_Matte,Left=%d,Top=%d,Right=%d,Bottom=%d",
box.left, box.top, box.right, box.bottom);
break;
case bPONT:
len = sizeof(Point);
ExtractBlockData(theBlock, &pt, &len);
err = SendStr(ref, (char*)"\pPoint #%d,h=%d,v=%d", theBlock->theID, pt.h, pt.v);
break;
case bMATI:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pMatteID=%d", sValue);
break;
case bVFLT:
err = SendStr(ref, (char*)"\pVideo_Filters", nil);
break;
case bAFLT:
err = SendStr(ref, (char*)"\pAudio_Filters", nil);
break;
case bFILT:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pFileID=%d", sValue);
break;
case bMOTN:
len = sizeof(Rect);
ExtractBlockData(theBlock, &box, &len);
err = SendStr(ref, (char*)"\pMotion,Left=%d,Top=%d,Right=%d,Bottom=%d",
box.left, box.top, box.right, box.bottom);
break;
case bSMTH:
err = SendStr(ref, (char*)"\pSmooth", nil);
break;
case bMREC:
len = sizeof(Rec_MREC);
ExtractBlockData(theBlock, &rMREC, &len);
err = SendStr(ref, (char*)"\pMotion_Point #%d,Zoom=%d,Time=%d,Delay=%d,Rotation=%d,h=%d,v=%d",
theBlock->theID, rMREC.zoom, rMREC.time, rMREC.delay, rMREC.rotation,
rMREC.spot.h, rMREC.spot.v);
break;
case bDATA:
err = SendStr(ref, (char*)"\pData #%d, %d bytes",
theBlock->theID, theBlock->dataSize);
break;
case bCLPB:
err = SendStr(ref, (char*)"\pClips", nil);
break;
case bCLIP:
len = sizeof(Rec_CLIP);
ExtractBlockData(theBlock, &rCLIP, &len);
err = SendStr(ref, (char*)"\pClipID #%d,FileID=%d,In=%d,Out=%d",
theBlock->theID, rCLIP.fileID, rCLIP.in, rCLIP.out);
break;
case bMARK:
len = sizeof(long);
ExtractBlockData(theBlock, &lValue, &len);
err = SendStr(ref, (char*)"\pMark #%d, Location=%d", theBlock->theID, lValue);
break;
case bLOCK:
err = SendStr(ref, (char*)"\pAspect_Locked", nil);
break;
case bRATE:
len = sizeof(short);
ExtractBlockData(theBlock, &sValue, &len);
err = SendStr(ref, (char*)"\pRate=%d", sValue);
break;
case bFILB:
err = SendStr(ref, (char*)"\pFiles", nil);
break;
case bFILE:
err = SendStr(ref, (char*)"\pFileID #%d", theBlock->theID);
break;
case bMACS:
len = sizeof(FSSpec);
ExtractBlockData(theBlock, &rFILE, &len);
err = SendStr(ref, (char*)"\pMac_Spec,Name='%s',vRefNum=%d,parID=%d",
(long)rFILE.name, rFILE.vRefNum, rFILE.parID);
break;
case bMACP:
len = 256;
if (p = NewPtr(256)) {
ExtractBlockData(theBlock, p, &len);
err = SendStr(ref, (char*)"\pMac_Path='%s'", (long)p);
DisposePtr(p);
}
break;
case bFRMS:
len = sizeof(long);
ExtractBlockData(theBlock, &lValue, &len);
err = SendStr(ref, (char*)"\pNum_Frames=%d", lValue);
break;
case bVIDI:
len = sizeof(Rec_VIDI);
ExtractBlockData(theBlock, &rVIDI, &len);
err = SendStr(ref, (char*)"\pVideo,Width=%d,Height=%d,Depth=%d",
rVIDI.frame.right, rVIDI.frame.bottom, rVIDI.depth);
break;
case bAUDI:
len = sizeof(long);
ExtractBlockData(theBlock, &lValue, &len);
err = SendStr(ref, (char*)"\pAudio,Rate=%d", lValue);
break;
case bTIMC:
if (pblock = NewPtr(256)) {
len = 256;
ExtractBlockData(theBlock, pblock, &len);
err = SendStr(ref, (char*)"\pTimecode String='%s'", (long)pblock);
DisposePtr(pblock);
}
break;
case bTIMB:
len = sizeof(Rec_TIMB);
ExtractBlockData(theBlock, &rTIMB, &len);
err = SendStr(ref, (char*)"\pTimecode Block,Frame=%d,DropFrame=%d,Format=%d",
rTIMB.frames, rTIMB.dropframe, rTIMB.format);
break;
case bREEL:
if (pblock = NewPtr(256)) {
len = 256;
ExtractBlockData(theBlock, pblock, &len);
err = SendStr(ref, (char*)"\pReel_Name='%s'", (long)pblock);
DisposePtr(pblock);
}
break;
default:
err = SendStr(ref, (char*)"\p'*** Unknown: '%t' #%d, %d bytes",
theBlock->type, theBlock->theID, theBlock->dataSize);
break;
}
// If there are any sub-blocks call ourselves recursively to parse them.
if (err == noErr && theBlock->size > (sizeof(BlockRec) + theBlock->dataSize)) {
err = SendChar(ref, ', ');
if (!err) SendChar(ref, kReturn);
count = CountTypeBlocks(-1, theBlock);
for (i = 0; i < count && err == noErr; i++)
err = ParseBlock(FindBlock(-1, -1, i, theBlock), ref, indent + 1);
SendIndent(ref, indent);
}
// Close this block and a comma if we're not at level 0. End with a CR.
if (err == noErr) err = SendChar(ref, ']');
if (err == noErr && indent) err = SendChar(ref, ', ');
if (err == noErr) err = SendChar(ref, kReturn);
return(err);
}
//========================================================================================
// Concatenate one data block onto the end of another, disposing the source handle
//========================================================================================
void AppendBlock(BlockRec **dstBlock, BlockRec **srcBlock)
{
HandAndHand((Handle)srcBlock, (Handle)dstBlock);
DisposeHandle((Handle)srcBlock);
}
//========================================================================================
// Add one data block into the end of another, disposing the source handle
//========================================================================================
void ExtendBlock(BlockRec **dstBlock, BlockRec **srcBlock)
{
HandAndHand((Handle)srcBlock, (Handle)dstBlock);
(*dstBlock)->size += GetHandleSize((Handle)srcBlock);
DisposeHandle((Handle)srcBlock);
}
//========================================================================================
// Skip to the next block
//========================================================================================
void NextBlock(BlockRec **srcBlock)
{
*((Ptr*)srcBlock) += (*srcBlock)->size;
}
//========================================================================================
// Count the number of blocks of a particular type. Pass -1 for type to count all types.
//========================================================================================
long CountTypeBlocks(long type, BlockRec *srcBlock)
{
long count;
BlockRec *end, *pos;
count = 0;
end = (BlockRec *)(((Ptr)srcBlock) + srcBlock->size);
pos = (BlockRec *)(((Ptr)srcBlock) + sizeof(BlockRec) + srcBlock->dataSize);
while (pos < end) {
if ((type == -1) || (pos->type == type))
count++;
NextBlock(&pos);
}
return(count);
}
//========================================================================================
// Build a block of data with a header
//========================================================================================
BlockRec **BuildBlock(long type, long theID, long length, void *data)
{
BlockRec therec;
Handle h;
therec.size = length + sizeof(BlockRec);
therec.dataSize = length;
therec.type = type;
therec.theID = theID;
h = NewHandle(0);
PtrAndHand((Ptr)&therec, h, sizeof(BlockRec));
if (length != 0)
PtrAndHand(data, h, length);
return((BlockRec **)h);
}
//========================================================================================
// Find a particular block. The parameters type, theID, or index may be -1 to indicate
// that they are ignored.
//========================================================================================
BlockRec *FindBlock(long type, long theID, long index, BlockRec *srcBlock)
{
long count;
BlockRec *end, *pos;
count = 0;
end = (BlockRec *)(((Ptr)srcBlock) + srcBlock->size);
pos = (BlockRec *)(((Ptr)srcBlock) + sizeof(BlockRec) + srcBlock->dataSize);
while (pos < end) {
if ((index == count) && ((type == -1) || (pos->type == type)))
return(pos);
else if ((pos->type == type && pos->theID == theID))
return(pos);
if ((type == -1) || (pos->type == type))
count++;
NextBlock(&pos);
}
return(nil);
}
//========================================================================================
// Return a handle to a numbered object
//========================================================================================
BlockRec **GetBlock(long type, long theID, long index, BlockRec **srcBlock)
{
BlockRec *destpos;
Handle h;
if (destpos = FindBlock(type, theID, index, *srcBlock)) {
PtrToHand((Ptr)destpos, &h, destpos->size);
return((BlockRec **)h);
} else return(nil);
}
//========================================================================================
// Copy the data from a numbered object
//========================================================================================
void ExtractBlockData(BlockRec *srcBlock, void *destination, long *maxlen)
{
long len;
len = srcBlock->dataSize>*maxlen? *maxlen:srcBlock->dataSize;
*maxlen = len;
BlockMove(((Ptr)srcBlock)+sizeof(BlockRec), destination, len);
}